﻿/*
 * dm104slaver.cpp
 *
 *  Created on: 2017年5月14日
 *      Author: work
 */

#include "dm104slaver.h"
#include <dm/os/log/logger.hpp>

static const char* logModule = "CDm104Slaver.apps.dm";

CDm104Slaver::CDm104Slaver():dm::os::protocol::CIec104Slaver(),m_callStep(CS_All),m_callTmpIndex(0){
	log().debug(THISMODULE "创建对象");
}

const char* CDm104Slaver::name()const{
	return "DM104从站";
}

CDm104Slaver::EAction CDm104Slaver::taskStart_call( const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	m_callStep = CS_Status;
	m_callTmpIndex = 0;

	m_taskCall = Started;
	return Action_Nothing;
}

CDm104Slaver::EAction CDm104Slaver::taskDo_call( const ts_t& ts,const rts_t& rts ){
	frame_apdu_t& apdu = txFrame().getApdu();

	EAction action = task_report(apdu,ts,rts);
	if( action!=Action_Nothing )
		return action;

	int count;

	switch( m_callStep ){
	case CS_Status:
		if( m_callTmpIndex<statusSize() ){
			count = statusSize() - m_callTmpIndex;
			if( count>frame_apdu_t::MaxCountOfObjs_3_M_DP_NA_1 )
				count = frame_apdu_t::MaxCountOfObjs_3_M_DP_NA_1;
			apdu.makeFrame_3_M_DP_NA_1(count,m_callTmpIndex+1,frame_apdu_t::FACause_introgen);
			for( int i=0;i<count;++i ){
				apdu.getInfo_3_M_DP_NA_1(i)->all = 0;
				apdu.getInfo_3_M_DP_NA_1(i)->bits.dpi = statusRt(m_callTmpIndex+i)->getValue().getValue();
			}

			log().info(THISMODULE "上传状态量 起始%d %d个，共%d",m_callTmpIndex,count,statusSize());
			m_callTmpIndex += count;
			if( m_callTmpIndex>=statusSize() ){
				m_callStep = CS_Discrete;
				m_callTmpIndex = 0;
			}

			return Action_SendAndReTime;
		}else{
			m_callStep = CS_Discrete;
			m_callTmpIndex = 0;
		}
		break;
	case CS_Discrete:
		if( m_callTmpIndex<discreteSize() ){
			count = discreteSize() - m_callTmpIndex;
			if( count>frame_apdu_t::MaxCountOfObjs_11_M_ME_NB_1 )
				count = frame_apdu_t::MaxCountOfObjs_11_M_ME_NB_1;
			apdu.makeFrame_11_M_ME_NB_1(count,m_callTmpIndex+1,frame_apdu_t::FACause_introgen);
			for( int i=0;i<count;++i ){
				apdu.getInfo_11_M_ME_NB_1(i)->all = discreteRt(m_callTmpIndex+i)->getValue().getValue();
				apdu.getInfo_11_M_ME_NB_1_qds(i)->all = 0;
			}

			log().info(THISMODULE "上传离散量 起始%d %d个，共%d",m_callTmpIndex,count,discreteSize());
			m_callTmpIndex += count;
			if( m_callTmpIndex>=discreteSize() ){
				m_callStep = CS_Measure;
				m_callTmpIndex = 0;
			}

			return Action_SendAndReTime;
		}else{
			m_callStep = CS_Measure;
			m_callTmpIndex = 0;
		}
		break;
	case CS_Measure:
		if( m_callTmpIndex<measureSize() ){
			count = measureSize() - m_callTmpIndex;
			if( count>frame_apdu_t::MaxCountOfObjs_13_M_ME_NC_1 )
				count = frame_apdu_t::MaxCountOfObjs_13_M_ME_NC_1;
			apdu.makeFrame_13_M_ME_NC_1(count,m_callTmpIndex+1,frame_apdu_t::FACause_introgen);
			for( int i=0;i<count;++i ){
				apdu.getInfo_13_M_ME_NC_1(i)->all = measureRt(m_callTmpIndex+i)->getValue().getValue();
				apdu.getInfo_13_M_ME_NC_1_qds(i)->all = 0;
			}

			log().info(THISMODULE "上传测量量 起始%d %d个，共%d",m_callTmpIndex,count,measureSize());
			m_callTmpIndex += count;
			if( m_callTmpIndex>=measureSize() ){
				m_callStep = CS_Cumulant;
				m_callTmpIndex = 0;
			}

			return Action_SendAndReTime;
		}else{
			m_callStep = CS_Cumulant;
			m_callTmpIndex = 0;
		}

		break;
	case CS_Cumulant:
		if( m_callTmpIndex<cumulantSize() ){
			count = cumulantSize() - m_callTmpIndex;
			if( count>frame_apdu_t::MaxCountOfObjs_15_M_IT_NA_1 )
				count = frame_apdu_t::MaxCountOfObjs_15_M_IT_NA_1;
			apdu.makeFrame_15_M_IT_NA_1(count,m_callTmpIndex+1,frame_apdu_t::FACause_introgen);
			for( int i=0;i<count;++i ){
				apdu.getInfo_15_M_IT_NA_1(i)->bits.counterReading = cumulantRt(m_callTmpIndex+i)->getValue().getValue();
			}

			log().info(THISMODULE "上传累计量 起始%d %d个，共%d",m_callTmpIndex,count,cumulantSize());
			m_callTmpIndex += count;
			if( m_callTmpIndex>=cumulantSize() ){
				m_callStep = CS_All;
				m_callTmpIndex = 0;
				m_taskCall = Success;
			}

			return Action_SendAndReTime;
		}else{
			m_callStep = CS_All;
			m_callTmpIndex = 0;
			m_taskCall = Success;
		}

		break;
	default:
		// 完成
		m_taskCall = Success;
		return Action_Nothing;
	}

	return Action_Nothing;
}

CDm104Slaver::EAction CDm104Slaver::taskEnd_call( const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	frame_apdu_t& apdu = txFrame().getApdu();

	apdu.makeFrame_100_C_IC_NA_1(m_callGroup,frame_apdu_t::FACause_actterm);

	m_taskCall = None;
	return Action_Nothing;
}

CDm104Slaver::EAction CDm104Slaver::task_none( const ts_t& ts,const rts_t& rts ){
	frame_apdu_t& apdu = txFrame().getApdu();

	return task_report(apdu,ts,rts);
}

CDm104Slaver::EAction CDm104Slaver::task_report( frame_apdu_t& /*tf*/,const ts_t& /*ts*/,const rts_t& /*rts*/ ){
	bool ov;

	dm::scada::CEvent event;
	while( m_em.tryGet(event,ov) ){
		if( event.type==dm::scada::CEvent::Status ){
			// 上报状态量
			break;
		}else if( event.type==dm::scada::CEvent::Discrete ){
			// 上报离散量
			break;
		}
	}

	dm::scada::CTimedMeasure tm;
	while( m_mm.tryGet(tm,ov) ){
		// 上报带时标的模拟量
		break;
	}

	dm::scada::CTimedCumulant tc;
	while( m_cm.tryGet(tc,ov) ){
		// 上报时标累计量
		break;
	}

	return Action_Nothing;
}
